package com.shop.cloud.controller.hongfu;

import java.io.BufferedOutputStream;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.json.JSONObject;
import org.json.XML;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.shop.cloud.common.mybatis.BaseController;
import com.shop.cloud.controller.pay.AlibbpayConfig;
import com.shop.cloud.controller.pay.WeixinPayConfig;
import com.shop.cloud.dao.hongfu.AlipayPrepayMsgDao;
import com.shop.cloud.dao.hongfu.WeixinPrepayMsgDao;
import com.shop.cloud.domain.hongfu.AlipayConfig;
import com.shop.cloud.domain.hongfu.AlipayPrepayMsg;
import com.shop.cloud.domain.hongfu.BalanceHistory;
import com.shop.cloud.domain.hongfu.IosWxParams;
import com.shop.cloud.domain.hongfu.PayMsgBean;
import com.shop.cloud.domain.hongfu.PointsConfig;
import com.shop.cloud.domain.hongfu.PointsHistory;
import com.shop.cloud.domain.hongfu.User;
import com.shop.cloud.domain.hongfu.WeixinConfig;
import com.shop.cloud.domain.hongfu.WeixinPrepayMsg;
import com.shop.cloud.filter.CurrentUserId;
import com.shop.cloud.filter.IgnoreAuth;
import com.shop.cloud.model.response.ObjectDataResponse;
import com.shop.cloud.service.hongfu.IAlipayConfigService;
import com.shop.cloud.service.hongfu.IAlipayPrepayMsgService;
import com.shop.cloud.service.hongfu.IBalanceHistoryService;
import com.shop.cloud.service.hongfu.IPointsConfigService;
import com.shop.cloud.service.hongfu.IPointsHistoryService;
import com.shop.cloud.service.hongfu.IUserService;
import com.shop.cloud.service.hongfu.IWeixinConfigService;
import com.shop.cloud.service.hongfu.IWeixinPrepayMsgService;

import io.swagger.annotations.ApiOperation;

/**
 * 提供app支付接口
 * @author Yan Weiwei
 *
 */
@RestController	
@RequestMapping(value = "api")
public class PayMsgController extends BaseController {
	
	private Logger logger = LoggerFactory.getLogger(PayMsgController.class);

	@Autowired
	private IWeixinConfigService weixinConfigService;
	
	@Autowired
	private IWeixinPrepayMsgService weixinPrepayMsgService;
	
	@Autowired
	private WeixinPrepayMsgDao weixinPrepayMsgDao;
	
	@Autowired
	private WeixinPayConfig weixinPayConfig;
	
	@Autowired
	private IUserService userService;
	
	@Autowired
	private IAlipayConfigService alipayConfigService;
	
	@Autowired
	private AlibbpayConfig alibbpayConfig;
	
	@Autowired
	private IAlipayPrepayMsgService alipayPrepayMsgService;
	
	@Autowired
	private AlipayPrepayMsgDao alipayPrepayMsgDao;
	
	@Autowired
    private IBalanceHistoryService balanceHistoryService;
	
	@Autowired
	private IPointsConfigService pointsConfigService;
	
	@Autowired
	private IPointsHistoryService pointsHistoryService;
	
	@ApiOperation(value = "获取微信配置信息", notes = "获取微信配置信息")
	@RequestMapping(value = "/weixinConfig", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<WeixinConfig> weixinConfig(@CurrentUserId Long userId){
		
		WeixinConfig weixinConfig = weixinConfigService.get(new Long(1));
		
		return new ObjectDataResponse<WeixinConfig>(weixinConfig);
	}
	
	@ApiOperation(value = "获取微信支付预订单-余额", notes = "获取微信支付预订单-余额")
	@RequestMapping(value = "/weixinPrepay", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<IosWxParams> weixinPrepay(@CurrentUserId Long userId, @RequestBody PayMsgBean payMsgBean){
		//关联交易流水号
		String tradeNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ((int)((Math.random()*9+1)*100000));
		
		IosWxParams iosWxParams = new IosWxParams(); 
		String prepay_id = null;
		try {
			prepay_id = weixinPayConfig.createPrepayOrder(tradeNo, payMsgBean.getIp(), payMsgBean.getOrderFee());
			
			//保存预订单信息
			WeixinPrepayMsg weixinPrepayMsg = new WeixinPrepayMsg();
			weixinPrepayMsg.setPrepayId(prepay_id);
			weixinPrepayMsg.setTradeNo(tradeNo);
			weixinPrepayMsg.setUserId(userId);
			weixinPrepayMsg.setCreateTime(new Timestamp((new Date()).getTime()));
			weixinPrepayMsgService.insert(weixinPrepayMsg);
			
			iosWxParams = weixinPayConfig.handleIosWxParams(prepay_id);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return new ObjectDataResponse<IosWxParams>(iosWxParams);
	}
	
	@IgnoreAuth
	@ApiOperation(value = "处理微信支付回调-余额", notes = "处理微信支付回调-余额")
	@RequestMapping(value = "/weixinCallback")
	@ResponseBody
	public void weixinCallback(@RequestBody String msg, HttpServletResponse response) throws Exception{
		
		logger.info("***************notify url get request xml params*****************"+msg);
		//初始化返回参数
		String return_code = "FAIL";
		String return_msg = "";
		
		JSONObject resultDatas = XML.toJSONObject(msg);
		JSONObject resultData = resultDatas.getJSONObject("xml");
		logger.info("***************notify url get request json params*****************"+resultData);
		
		//结果状态码
        String result_code = resultData.getString("result_code");
        //交易金额
        double total_fee = resultData.getDouble("total_fee");
        total_fee = total_fee / 100;
        //流水号
        String out_trade_no = resultData.getString("out_trade_no");
        
        if(result_code.equals("SUCCESS")){
        	//交易成功
        	//保存充值流水
        	Map<String, String> map = new HashMap<String, String>();
        	map.put("tradeNo", out_trade_no);
        	
        	WeixinPrepayMsg weixinPrepayMsg = weixinPrepayMsgDao.getThisByTradeNo(map);
        	//修改用户余额
        	if(null != weixinPrepayMsg){
        		Long userId = weixinPrepayMsg.getUserId();
        		User user = userService.get(userId);
        		//获取用户余额
        		Float balance = user.getBalance();
        		BigDecimal payFee = new BigDecimal(total_fee);
        		payFee = payFee.setScale(2, BigDecimal.ROUND_HALF_DOWN);
        		BigDecimal thisFee = new BigDecimal(balance);
        		
        		BigDecimal resultFee = payFee.add(thisFee);
        		resultFee = resultFee.setScale(2, BigDecimal.ROUND_HALF_DOWN);
        		user.setBalance(resultFee.floatValue());
        		//保存修改
        		userService.update(user);
        		
        		BalanceHistory balanceHistory = new BalanceHistory();
				balanceHistory.setUserId(userId);
				balanceHistory.setType(1);
				balanceHistory.setAmount(payFee.floatValue());
				balanceHistory.setAccountType(2);
				balanceHistory.setOrderNo(out_trade_no);
				balanceHistory.setCreateTime(new Timestamp((new Date()).getTime()));
				balanceHistory.setRemark(user.getNickname()+"使用微信支付,充值"+payFee+"元余额");
				//创建流水
				balanceHistoryService.insert(balanceHistory);
        	}
        	weixinPrepayMsg.setType(2);
        	//修改预订单已支付
        	weixinPrepayMsgService.update(weixinPrepayMsg);
        	
        	return_code = "SUCCESS";
            return_msg = "OK";
        }else{
        	//交易失败
        	return_msg = "INVALID SIGNATURE OR MSG FAIL";
        }
        
        String resultXML = "<xml><return_code><![CDATA["+return_code+"]]></return_code><return_msg><![CDATA["+return_msg+"]]></return_msg></xml>";
        logger.info("***************result xml info*****************"+resultXML);
        
        response.setContentType("text/xml;charset=UTF-8");
		response.setHeader("Cache-Control", "no-cache");
		
		response.getWriter().print(resultXML);
	}
	
	@ApiOperation(value = "获取微信支付状态-余额", notes = "获取微信支付状态-余额")
	@RequestMapping(value = "/getWeixinPrepayType", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<Integer> getWeixinPrepayType(@CurrentUserId Long userId, @RequestBody PayMsgBean payMsgBean){
		int type = 0;
		
		WeixinPrepayMsg weixinPrepayMsg = new WeixinPrepayMsg();
		weixinPrepayMsg.setUserId(userId);
		weixinPrepayMsg.setTradeNo(payMsgBean.getTradeNo());
		
		WeixinPrepayMsg thisData = weixinPrepayMsgService.findOne(weixinPrepayMsg);
		if(null != thisData){
			type = thisData.getType();
		}
		
		return new ObjectDataResponse<Integer>(type);
	}
	
	@ApiOperation(value = "获取微信支付预订单-积分", notes = "获取微信支付预订单-积分")
	@RequestMapping(value = "/weixinPrepayForPoints", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<IosWxParams> weixinPrepayForPoints(@CurrentUserId Long userId, @RequestBody PayMsgBean payMsgBean){
		//关联交易流水号
		String tradeNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ((int)((Math.random()*9+1)*100000));
		
		IosWxParams iosWxParams = new IosWxParams(); 
		String prepay_id = null;
		try {
			prepay_id = weixinPayConfig.createPrepayOrderForPonits(tradeNo, payMsgBean.getIp(), payMsgBean.getOrderFee());
			
			//保存预订单信息
			WeixinPrepayMsg weixinPrepayMsg = new WeixinPrepayMsg();
			weixinPrepayMsg.setPrepayId(prepay_id);
			weixinPrepayMsg.setTradeNo(tradeNo);
			weixinPrepayMsg.setUserId(userId);
			weixinPrepayMsg.setCreateTime(new Timestamp((new Date()).getTime()));
			weixinPrepayMsgService.insert(weixinPrepayMsg);
			
			iosWxParams = weixinPayConfig.handleIosWxParams(prepay_id);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return new ObjectDataResponse<IosWxParams>(iosWxParams);
	}
	
	@IgnoreAuth
	@ApiOperation(value = "处理微信支付回调-积分", notes = "处理微信支付回调-积分")
	@RequestMapping(value = "/weixinCallbackForPoints")
	@ResponseBody
	public void weixinCallbackForPoints(@RequestBody String msg, HttpServletResponse response) throws Exception{
		
		logger.info("***************notify url get request xml params*****************"+msg);
		//初始化返回参数
		String return_code = "FAIL";
		String return_msg = "";
		
		JSONObject resultDatas = XML.toJSONObject(msg);
		JSONObject resultData = resultDatas.getJSONObject("xml");
		logger.info("***************notify url get request json params*****************"+resultData);
		
		//结果状态码
        String result_code = resultData.getString("result_code");
        //交易金额
        double total_fee = resultData.getDouble("total_fee");
        total_fee = total_fee / 100;
        //流水号
        String out_trade_no = resultData.getString("out_trade_no");
        
        if(result_code.equals("SUCCESS")){
        	PointsConfig pointsConfig = pointsConfigService.get(new Long(1));
        	if(null != pointsConfig){
        		total_fee = total_fee * pointsConfig.getScale();
        	}
        	//交易成功
        	//保存充值流水
        	Map<String, String> map = new HashMap<String, String>();
        	map.put("tradeNo", out_trade_no);
        	
        	WeixinPrepayMsg weixinPrepayMsg = weixinPrepayMsgDao.getThisByTradeNo(map);
        	//修改用户积分
        	if(null != weixinPrepayMsg){
        		Long userId = weixinPrepayMsg.getUserId();
        		User user = userService.get(userId);
        		//获取用户积分
        		int points = user.getPoints();
        		int result = points + (int)total_fee;
        		user.setPoints(result);
        		//保存修改
        		userService.update(user);
        		
        		BalanceHistory balanceHistory = new BalanceHistory();
				balanceHistory.setUserId(userId);
				balanceHistory.setType(21);
				balanceHistory.setCredits((int)total_fee);
				balanceHistory.setAccountType(2);
				balanceHistory.setOrderNo(out_trade_no);
				balanceHistory.setCreateTime(new Timestamp((new Date()).getTime()));
				balanceHistory.setRemark(user.getNickname()+"使用微信支付,充值"+total_fee+"积分");
				//创建流水
				balanceHistoryService.insert(balanceHistory);
				
				PointsHistory pointsHistory = new PointsHistory();
				pointsHistory.setUserId(userId);
				pointsHistory.setType(10);
				pointsHistory.setCurrentPoints(user.getPoints());
				pointsHistory.setChangePoints((int)total_fee);
				pointsHistory.setCreateTime(new Timestamp((new Date()).getTime()));
				pointsHistory.setPointNo(out_trade_no);
				pointsHistoryService.insert(pointsHistory);
        	}
        	weixinPrepayMsg.setType(2);
        	//修改预订单已支付
        	weixinPrepayMsgService.update(weixinPrepayMsg);
        	
        	return_code = "SUCCESS";
            return_msg = "OK";
        }else{
        	//交易失败
        	return_msg = "INVALID SIGNATURE OR MSG FAIL";
        }
        
        String resultXML = "<xml><return_code><![CDATA["+return_code+"]]></return_code><return_msg><![CDATA["+return_msg+"]]></return_msg></xml>";
        logger.info("***************result xml info*****************"+resultXML);
        
        response.setContentType("text/xml;charset=UTF-8");
		response.setHeader("Cache-Control", "no-cache");
		
		response.getWriter().print(resultXML);
	}
	
	@ApiOperation(value = "获取支付宝支付预订单-余额", notes = "获取支付宝支付预订单-余额")
	@RequestMapping(value = "/alipayPrepay", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<Map<String, Object>> alipayPrepay(@CurrentUserId Long userId, @RequestBody PayMsgBean payMsgBean){
		//关联交易流水号
		String tradeNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ((int)((Math.random()*9+1)*100000));
		
		String data = null;
		try {
			data = alibbpayConfig.getAlipayOrder(tradeNo, payMsgBean.getOrderFee());
			
			//保存支付宝订单信息
			AlipayPrepayMsg alipayPrepayMsg = new AlipayPrepayMsg();
			alipayPrepayMsg.setUserId(userId);
			alipayPrepayMsg.setTradeNo(tradeNo);
			alipayPrepayMsg.setCreateTime(new Timestamp((new Date()).getTime()));
			
			alipayPrepayMsgService.insert(alipayPrepayMsg);
			
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
	    Map<String, Object> map = new HashMap<String, Object>();
	    map.put("key", data);
		
		return new ObjectDataResponse<Map<String, Object>>(map);
	}
	
	 /**
     * 支付宝支付回调
     */
	@IgnoreAuth
	@ApiOperation(value = "支付宝支付回调-余额", notes = "支付宝支付回调-余额")
	@RequestMapping(value = "/alipayNotify")
	public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String message = "success";
		
		AlipayConfig alipayConfig = alipayConfigService.get(new Long(1));
		
		Map<String, String> params = new HashMap<String, String>();
		// 取出所有参数是为了验证签名
		Enumeration<String> parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements()) {
			String parameterName = parameterNames.nextElement();
			params.put(parameterName, request.getParameter(parameterName));
		}
		//验证签名 校验签名
		boolean signVerified = false;
		
		String signType=params.get("sign_type");
		try {
			signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayProPublicKey(), "UTF-8", signType);
		} catch (AlipayApiException e) {
			e.printStackTrace();
			message =  "failed";
		}
		if (signVerified) {
			logger.info("支付宝验证签名成功！");
			// 若参数中的appid和填入的appid不相同，则为异常通知
			if (!alipayConfig.getAppid().equals(params.get("app_id"))) {
				logger.info("与付款时的appid不同，此为异常通知，应忽略！");
				message =  "failed";
			}else{
				//处理回调逻辑
				String out_trade_no = params.get("out_trade_no");
				String total_fee = params.get("total_amount");
				Map<String, String> map = new HashMap<String, String>();
	        	map.put("tradeNo", out_trade_no);
	        	
				AlipayPrepayMsg alipayPrepayMsg = alipayPrepayMsgDao.getThisByTradeNo(map);
				if(null != alipayPrepayMsg){
					Long userId = alipayPrepayMsg.getUserId();
	        		User user = userService.get(userId);
	        		if(null != user){
	        			//获取用户余额
		        		Float balance = user.getBalance();
		        		BigDecimal payFee = new BigDecimal(total_fee);
		        		BigDecimal thisFee = new BigDecimal(balance);
		        		
		        		BigDecimal resultFee = payFee.add(thisFee);
		        		resultFee = resultFee.setScale(2, BigDecimal.ROUND_HALF_DOWN);
		        		user.setBalance(resultFee.floatValue());
		        		//保存修改
		        		userService.update(user);
		        		
		        		BalanceHistory balanceHistory = new BalanceHistory();
						balanceHistory.setUserId(userId);
						balanceHistory.setType(1);
						balanceHistory.setAmount(payFee.floatValue());
						balanceHistory.setAccountType(1);
						balanceHistory.setOrderNo(out_trade_no);
						balanceHistory.setCreateTime(new Timestamp((new Date()).getTime()));
						balanceHistory.setRemark(user.getNickname()+"使用支付宝支付,充值"+payFee+"元余额");
						//创建流水
						balanceHistoryService.insert(balanceHistory);
	        		}
				}
			}
		} else { // 如果验证签名没有通过
			message =  "failed";
			logger.info("验证签名失败！");
		}
		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
		out.write(message.getBytes());
		out.flush();
		out.close();
	}
	
	@ApiOperation(value = "获取支付宝支付预订单-积分", notes = "获取支付宝支付预订单-积分")
	@RequestMapping(value = "/alipayPrepayForPoints", method = RequestMethod.POST)
	@ResponseBody
	public ObjectDataResponse<Map<String, Object>> alipayPrepayForPoints(@CurrentUserId Long userId, @RequestBody PayMsgBean payMsgBean){
		//关联交易流水号
		String tradeNo = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ((int)((Math.random()*9+1)*100000));
		
		String data = null;
		try {
			data = alibbpayConfig.getAlipayOrderForPoints(tradeNo, payMsgBean.getOrderFee());
			
			//保存支付宝订单信息
			AlipayPrepayMsg alipayPrepayMsg = new AlipayPrepayMsg();
			alipayPrepayMsg.setUserId(userId);
			alipayPrepayMsg.setTradeNo(tradeNo);
			alipayPrepayMsg.setCreateTime(new Timestamp((new Date()).getTime()));
			
			alipayPrepayMsgService.insert(alipayPrepayMsg);
			
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
	    Map<String, Object> map = new HashMap<String, Object>();
	    map.put("key", data);
		
		return new ObjectDataResponse<Map<String, Object>>(map);
	}
	
	 /**
     * 支付宝支付回调
     */
	@IgnoreAuth
	@ApiOperation(value = "支付宝支付回调-积分", notes = "支付宝支付回调-积分")
	@RequestMapping(value = "/alipayNotifyForPoints")
	public void alipayNotifyForPoints(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String message = "success";
		
		AlipayConfig alipayConfig = alipayConfigService.get(new Long(1));
		
		Map<String, String> params = new HashMap<String, String>();
		// 取出所有参数是为了验证签名
		Enumeration<String> parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements()) {
			String parameterName = parameterNames.nextElement();
			params.put(parameterName, request.getParameter(parameterName));
		}
		//验证签名 校验签名
		boolean signVerified = false;
		
		String signType=params.get("sign_type");
		try {
			signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayProPublicKey(), "UTF-8", signType);
		} catch (AlipayApiException e) {
			e.printStackTrace();
			message =  "failed";
		}
		if (signVerified) {
			logger.info("支付宝验证签名成功！");
			// 若参数中的appid和填入的appid不相同，则为异常通知
			if (!alipayConfig.getAppid().equals(params.get("app_id"))) {
				logger.info("与付款时的appid不同，此为异常通知，应忽略！");
				message =  "failed";
			}else{
				//处理回调逻辑
				String out_trade_no = params.get("out_trade_no");
				String total_fee = params.get("total_amount");
				PointsConfig pointsConfig = pointsConfigService.get(new Long(1));
				int totalFee = 0;
				if(null != pointsConfig){
					totalFee = (int)(new Float(total_fee) * pointsConfig.getScale());
				}
				Map<String, String> map = new HashMap<String, String>();
	        	map.put("tradeNo", out_trade_no);
	        	
				AlipayPrepayMsg alipayPrepayMsg = alipayPrepayMsgDao.getThisByTradeNo(map);
				if(null != alipayPrepayMsg){
					Long userId = alipayPrepayMsg.getUserId();
	        		User user = userService.get(userId);
	        		if(null != user){
	        			//获取用户积分
	        			int points = user.getPoints();
	            		int result = points + totalFee;
	            		user.setPoints(result);
		        		//保存修改
		        		userService.update(user);
		        		
		        		BalanceHistory balanceHistory = new BalanceHistory();
						balanceHistory.setUserId(userId);
						balanceHistory.setType(21);
						balanceHistory.setCredits(totalFee);
						balanceHistory.setAccountType(1);
						balanceHistory.setOrderNo(out_trade_no);
						balanceHistory.setCreateTime(new Timestamp((new Date()).getTime()));
						balanceHistory.setRemark(user.getNickname()+"使用支付宝支付,充值"+totalFee+"积分");
						//创建流水
						balanceHistoryService.insert(balanceHistory);
						
						PointsHistory pointsHistory = new PointsHistory();
						pointsHistory.setUserId(userId);
						pointsHistory.setType(10);
						pointsHistory.setCurrentPoints(user.getPoints());
						pointsHistory.setChangePoints(totalFee);
						pointsHistory.setCreateTime(new Timestamp((new Date()).getTime()));
						pointsHistory.setPointNo(out_trade_no);
						pointsHistoryService.insert(pointsHistory);
	        		}
				}
			}
		} else { // 如果验证签名没有通过
			message =  "failed";
			logger.info("验证签名失败！");
		}
		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
		out.write(message.getBytes());
		out.flush();
		out.close();
	}
	
}
